CHAPTER 10 ■ REACT-BOOTSTRAP
219
Bootstrap then takes care of laying them out and deciding how to fit the cells at different
screen widths. In the filter, we have three cells, of roughly equal width: status input, effort
inputs, and the buttons. We don’t want to break either the effort inputs or the buttons into
multiple lines even on very small screens, so we’ll treat them as one cell each.
Let’s start with the smallest screen size: a mobile device. Let’s use half the screen
width per cell. This will mean that we’ll have Status and Effort on one line, and the
buttons in the next. This can be achieved by specifying xs={6} for each of the cells, that
is, half the total available 12 columns. You may wonder how 3 cells of 6 columns each,
totaling 18 columns, can fit a row of 12 columns. But the fact is that the grid system wraps
the last 6 columns into another line (not row, mind you).
It’s best to compare the fluid grid system with paragraphs and lines. Rows are
like paragraphs rather than lines. A paragraph (row) can contain multiple lines. As the
paragraph width (screen width) reduces, it will need more lines. It’s only when you want
to break two sets of sentences (sets of cells) that you really need another paragraph (row).
Most people take some time to appreciate this aspect of the fluid grid system, because
many popular examples show rows and columns in a fixed grid rather than a fluid one,
and therefore lay out the screen in multiple rows.
Next, let’s consider a slightly bigger screen: a tablet, in landscape mode. The property
for this size is sm. Let’s fill the screen width with all three cells in one line. We must use a
width of 4 columns for each, thus specifying sm={4} for these cells. If we had more cells,
then this too would wrap into multiple lines but since we have exactly three, this will fit
the screen in one line.
On larger screens like desktops, we can let each cell continue to occupy 4 columns
each, which doesn’t require any more property specifications. But I think it looks ungainly
if the form controls stretch too much, so let’s reduce the width of the cells using md={3}
and lg={2}. This will cause the trailing columns on larger screens to be unoccupied.
Now, for the contents of each cell in the grid. The most common usage is to use
a FormGroup component that encloses a FormLabel for the label of the control and a
FormControl component for the actual control. A FormControl has a componentClass
property that specifies the component class of the actual element that is rendered, such
as input, select, and textarea. It can even be our own custom class instead of the built-
in HTML elements. The status drop-down fits this pattern, with the options as children of
the FormControl.
The Effort inputs are not that straightforward since they’re made up of two inputs.
We can use an InputGroup to enclose the two FormControls, but by itself, it will cause the
two inputs to show one below the other. The InputGroup.Addon component can be used
to display the inputs next to each other, as well as show the dash between the two inputs.
We’ll use a ButtonToolbar for the set of buttons in the last cell. There is no label for
this, but to align the buttons with the controls, we need an empty label. The code for the
new render() method of IssueFilter is shown in Listing 10-11.
Listing 10-11. IssueFilter.jsx: New render() Method, and Required Imports
...
import { Col, Row, FormGroup, FormControl, ControlLabel, InputGroup,
ButtonToolbar, Button } from 'react-bootstrap';
...
render() {
return (